package com.ae.shield.common.items;

import com.ae.shield.AEShieldMod;
import com.ae.shield.api.IEnergyItem;
import com.ae.shield.api.IShield;
import com.ae.shield.api.IStorageItem;
import com.ae.shield.common.capability.Itemhandler.ModItemStackHandler;
import com.ae.shield.common.capability.energy.ItemEnergyStorage;
import com.ae.shield.common.gui.container.ShieldContainer;
import com.ae.shield.common.events.ShieldProtectEvent;
import com.ae.shield.common.items.shieldFittings.makers.NanoRobot;
import com.ae.shield.common.items.shieldFittings.rectifier.CapacitorBank;
import com.ae.shield.common.items.shieldFittings.makers.ShieldMakerBase;
import com.ae.shield.common.items.util.ItemNBTHelper;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.inventory.container.SimpleNamedContainerProvider;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;

public class ItemIntegratedShield extends Item implements IEnergyItem, IStorageItem {
    private static final int slotSize = 9;

    public ItemIntegratedShield() {
        super(new Properties().maxStackSize(1).group(AEShieldMod.AE_SHIELD));

    }

//-----------------------------------------------能量条显示---------------------------------------------------------------

    @Override
    public boolean showDurabilityBar(ItemStack stack) {
        return true;
    }

    @Override
    public double getDurabilityForDisplay(ItemStack stack) {
        return 1 - (double) getEnergyCap(stack).getEnergyStored() / (double) getEnergyCapacity();
    }

    @Override
    public int getRGBDurabilityForDisplay(ItemStack stack) {
        return -14748417;
    }

//----------------------------------------------添加满能量到创造物品栏------------------------------------------------------

    @Override
    public void fillItemGroup(@Nonnull ItemGroup group, @Nonnull NonNullList<ItemStack> items) {
        if (this.isInGroup(group)) {
            for (int i = 0; i < 2; i++) {
                ItemStack stack = new ItemStack(this);
                ItemNBTHelper.setInt(stack, "fe_energy", getEnergyCapacity() * i);
                items.add(stack);
            }
        }
    }

//----------------------------------------------------------------------------------------------------------------------

    @Nonnull
    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, @Nonnull PlayerEntity playerIn, @Nonnull Hand handIn) {
        if (!worldIn.isRemote) {
            ItemStack stack = playerIn.getHeldItem(handIn);
            INamedContainerProvider container = new SimpleNamedContainerProvider((id, playerInventory, pl) -> new ShieldContainer(id, playerInventory, stack), stack.getDisplayName());
            NetworkHooks.openGui((ServerPlayerEntity) playerIn, container, b -> b.writeItemStack(stack));
        }
        return ActionResult.resultSuccess(playerIn.getHeldItem(handIn));
    }

    @Override
    public void addInformation(@Nonnull ItemStack stackIn, @Nullable World world, @Nonnull List<ITextComponent> components, @Nonnull ITooltipFlag tooltipFlag) {
        ITextComponent energy = new StringTextComponent(Integer.toString(getEnergyCap(stackIn).getEnergyStored())).mergeStyle(TextFormatting.BLUE);
        ITextComponent maxEnergy = new StringTextComponent(Integer.toString(getEnergyCapacity())).mergeStyle(TextFormatting.WHITE);
        components.add(new TranslationTextComponent("tooltip.ae.shield.energy1").mergeStyle(TextFormatting.GRAY));
        components.add(new TranslationTextComponent("tooltip.ae.shield.energy2", energy, maxEnergy).mergeStyle(TextFormatting.WHITE));
    }

    @Override
    public void inventoryTick(@Nonnull ItemStack stack, @Nonnull World world, @Nonnull Entity entity, int itemSlot, boolean isSelected) {
        if (!world.isRemote && entity instanceof PlayerEntity) {
            NonNullList<ItemStack> stacks = getInventory(stack);

            float cdReduce = 1;
            int charging = stacks.size() - 1;
            boolean nano = true;
            boolean isWorking = false;
            for (int i = stacks.size() - 1; i > -1; i--) {
                ItemStack shieldStack = stacks.get(i);

                if (!(shieldStack.getItem() instanceof ShieldMakerBase)) {
                    charging--;

                    //冷却减免
                    if (shieldStack.getItem() instanceof CapacitorBank) {
                        CapacitorBank capacitorBank = (CapacitorBank) shieldStack.getItem();
                        cdReduce += capacitorBank.cdReduce(shieldStack, getEnergyCap(stack), shieldStack);
                    }

                    continue;
                }

                ShieldMakerBase maker = (ShieldMakerBase) shieldStack.getItem();

                //配合属性复写实现材质变化
                float intensity = maker.getIntensity(shieldStack);
                if (intensity > 0) {
                    isWorking = true;
                }

                if (maker.getItem() instanceof NanoRobot) {
                    if (nano) {
                        maker.shieldTick(shieldStack, world, entity, getEnergyCap(stack));
                        nano = false;
                    }
                } else {
                    maker.shieldTick(shieldStack, world, entity, getEnergyCap(stack));
                }

                //护盾恢复
                if (maker.getCD(shieldStack) <= 0) {
                    if (charging == i) {
                        if (maker.getPlies(shieldStack) >= maker.finalMaxPiles(shieldStack) && maker.getIntensity(shieldStack) >= maker.finalMaxIntensity(shieldStack)) {
                            charging--;
                        } else {
                            maker.rebuildShield(shieldStack, getEnergyCap(stack));
                        }
                    }
                } else {
                    float a = maker.getCD(shieldStack) - cdReduce;
                    maker.setCD(shieldStack, a < 0 ? 0 : a);
                }

            }

            if (isWorking) {
                ItemNBTHelper.setInt(stack, "isWorking", 1);
            } else {
                ItemNBTHelper.setInt(stack, "isWorking", 0);
            }

        }
    }

    @Override
    public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
        return false;
    }

    @Override
    public int getSlots() {
        return slotSize;
    }

    public int isWorking(ItemStack stack) {
        if (stack.getItem() instanceof ItemIntegratedShield) {
            return ItemNBTHelper.getInt(stack, "isWorking", 0);
        } else throw new IllegalArgumentException("输入的stack物品不是ItemIntegratedShield");
    }

//--------------------------------------处理掉落在世界中的实体--------------------------------------------------------------

    @Override
    public boolean hasCustomEntity(ItemStack stack) {
        return true;
    }

    @Nullable
    @Override
    public Entity createEntity(World world, Entity location, ItemStack itemstack) {
        return super.createEntity(world, location, itemstack);
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 该方法由 ShieldProtectEvent 触发
     *
     * @return 返回攻击在经过抵挡后的剩余
     * @see ShieldProtectEvent
     */
    public float onEntityHurt(LivingEntity entity, ItemStack stack, float amount, DamageSource source) {
        if (stack.isEmpty()) {
            return amount;
        }

        NonNullList<ItemStack> inv = getInventory(stack);
        float residue = amount;
        ItemStack finalShield = null;
        for (ItemStack makerStack : inv) {
            Item makerItem = makerStack.getItem();
            if (makerStack.isEmpty() || !(makerItem instanceof IShield)) {
                continue;
            }

            IShield shieldMaker = (IShield) makerItem;
            residue = shieldMaker.onEntityHurt(entity, makerStack, residue, source, getEnergyCap(stack));
            finalShield = makerStack;
            if (residue <= 0) {
                break;
            }
        }

        //生成护盾受击后的音效
        World world = entity.world;
        if (residue != amount && finalShield != null && finalShield.getItem() instanceof ShieldMakerBase) {
            ShieldMakerBase shield = (ShieldMakerBase) finalShield.getItem();
            if (shield.getPlies(finalShield) < 1) {
                shield.playBreakVoice(world, entity);
            } else {
                shield.playDefenseVoice(world, entity);
            }
        }

        return residue;
    }

    /**
     * 该方法由 ShieldProtectEvent 触发
     *
     * @return true 避免死亡
     * @see ShieldProtectEvent
     */
    public boolean onEntityDeath(ItemStack stack, LivingEntity entity, DamageSource source) {
        if (stack.isEmpty()) {
            return false;
        }

        NonNullList<ItemStack> inv = getInventory(stack);
        for (ItemStack itemStack : inv) {
            Item item = itemStack.getItem();
            if (!(item instanceof IShield)) {
                continue;
            }

            IShield rectifier = (IShield) item;
            if (rectifier.onEntityDeath(itemStack, entity, source, getEnergyCap(stack))) {
                return true;
            }
        }

        return false;
    }

    public static NonNullList<ItemStack> getInventory(ItemStack stack) {
        LazyOptional<IItemHandler> lazyOptional = stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
        IItemHandler cap1 = lazyOptional.orElseThrow(() -> new IllegalArgumentException("ItemStack does not contain ITEM_HANDLER_CAPABILITY. Input " + stack.getItem() + "."));

        if (cap1 instanceof ModItemStackHandler) {
            return ((ModItemStackHandler) cap1).getInv();
        } else {
            throw new IllegalArgumentException("ItemStack's cap not instanceof ModItemStackHandler. Input " + stack.getItem() + ".");
        }
    }

//-------------------------------------------------能量操作--------------------------------------------------------------

    @Override
    public int getEnergyCapacity() {
        return 100000;
    }

    @Override
    public int getMaxReceive() {
        return 10000;
    }

    @Override
    public int getMaxExtract() {
        return 10000;
    }

    public IEnergyStorage getEnergyCap(ItemStack stack) {
        LazyOptional<IEnergyStorage> lazyOptional = stack.getCapability(CapabilityEnergy.ENERGY);
        return lazyOptional.orElse(new ItemEnergyStorage(stack, getEnergyCapacity(), getMaxExtract(), getMaxReceive()));
    }

    @Override
    public int receiveEnergy(ItemStack stack, int maxReceive, boolean simulate) {
        IEnergyStorage storage = getEnergyCap(stack);
        return storage.receiveEnergy(maxReceive, simulate);
    }

    public int extractEnergy(ItemStack stack, int maxExtract, boolean simulate) {
        IEnergyStorage storage = getEnergyCap(stack);
        return storage.extractEnergy(maxExtract, simulate);
    }
}
